package com.pro.common.jwt;

import com.pro.framework.api.entity.IBaseProperties;
import com.pro.common.api.enums.EnumSysRole;
import com.pro.common.api.model.ILoginInfo;
import com.pro.common.api.model.LoginInfo;
import com.pro.common.api.common.model.ICommonProperties;
import io.jsonwebtoken.*;
import io.swagger.v3.oas.annotations.Parameter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@Slf4j
public class JwtClaimsService implements IJwtClaimsService {
    @Autowired
    private JwtProperties jwtProperties;
    @Autowired
    private ICommonProperties commonProperties;
    @Autowired
    private IBaseProperties baseProperties;

    public ILoginInfo claimsToLogin(Claims claims) {
        LoginInfo loginInfo = new LoginInfo();
        loginInfo.setId(claims.get("id", Long.class));
        loginInfo.setSysRole(EnumSysRole.MAP.get(claims.get("sysRole", String.class)));
        loginInfo.setUsername(claims.get("username", String.class));
        loginInfo.setIsDemo(claims.get("isDemo", Boolean.class));
        loginInfo.setIsGuest(claims.get("isGuest", Boolean.class));
        loginInfo.setAuthRouteGroupCode(claims.get("authRouteGroupCode", String.class));
        return loginInfo;
    }

    public JwtBuilder loginToClaim(ILoginInfo loginInfo, JwtBuilder builder) {
        builder.claim("id", loginInfo.getId()).claim("sysRole", loginInfo.getSysRole()).claim("username", loginInfo.getUsername()).claim("isDemo", loginInfo.getIsDemo()).claim("isGuest", loginInfo.getIsGuest()).claim("authRouteGroupCode", loginInfo.getAuthRouteGroupCode());
        return builder;
    }

    /**
     * 根据 Jtw_token
     * 生成 用户资料
     */
    @Override
    public ILoginInfo tokenToLogin(String token, String origin, EnumSysRole sysRole, String path, boolean isPublic) {
        Claims claims;
        if (token == null || token.length() < 10 || token.chars().filter(ch -> ch == '.').count() != 2) {
            if (null != token && !token.isEmpty() && !isPublic) {
                log.warn("鉴权失败 token error, path:{}, origin:{}, sysRole:{}, token: {}", path, origin, sysRole, token);
            }
            return this.tokenToLoginErrorDefault(origin, sysRole);
        }
        try {
            claims = Jwts.parser().setSigningKey(jwtProperties.getSecretKey().getBytes(StandardCharsets.UTF_8)).parseClaimsJws(token).getBody();
        } catch (Exception e) {
            log.warn("鉴权失败 token Exception, path:{}, origin:{}, sysRole:{}, token: {} {}", path, origin, sysRole, token, e.getMessage());
            return this.tokenToLoginErrorDefault(origin, sysRole);
        }
        ILoginInfo iLoginInfo = null;
        try {
            iLoginInfo = this.claimsToLogin(claims);
        } catch (Exception e) {
            log.error("claimsToLogin error {}", e.getMessage(), e);
            return this.tokenToLoginErrorDefault(origin, sysRole);
        }
        return iLoginInfo;
    }


    /**
     * 根据用户资料 Jtw_token
     * 生成 Jtw_token
     */
    @Override
    public AccessTokenJwt loginToToken(@Parameter(hidden = true) ILoginInfo loginInfo) {
        Integer second = jwtProperties.getRoleSecondMap().get(loginInfo.getSysRole());
        long EXPIRATION_TIME = second * 1000;
        JwtBuilder builder = Jwts.builder();
        builder = this.loginToClaim(loginInfo, builder);
        Date exp = new Date(System.currentTimeMillis() + EXPIRATION_TIME);
        SignatureAlgorithm algorithm = AccessTokenJwt.defaultAlgorithm;
        String token = builder.setExpiration(exp).signWith(algorithm, jwtProperties.getSecretKey().getBytes(StandardCharsets.UTF_8)).compact();
        return new AccessTokenJwt(token, exp.getTime(), AccessTokenJwt.defaultTokenType, algorithm);
    }

    private ILoginInfo tokenToLoginErrorDefault(String origin, EnumSysRole sysRole) {
//        if (EnumEnv.prod.equals(baseProperties.getCommonEnv())) {
//            return new LoginInfo(EnumSysRole.ANONYMOUS, -9999L, null, null);
//        }
        Long id = commonProperties.getTestRoleLoginIdMap().get(sysRole);
//        if (null == id && "Knife4j".equals(origin)) {
//            id = 1L;
//        }
        if (id == null) {
//            if (EnumEnv.dev.equals(baseProperties.getCommonEnv())) {
//                id = 1L;
//            }
        }
        if (null != id && id == 1L) {
            switch (sysRole) {
                case USER:
                case ANONYMOUS:
                    return new LoginInfo(sysRole, id, "13800000000", true);
            }
        }
        if (id == null) {
            return new LoginInfo(EnumSysRole.ANONYMOUS, -9999L, null, false);
        }
        return new LoginInfo(sysRole, id, null, false);
    }


    // 添加这些辅助方法到您的类中
    protected Long safeToLong(Object obj) {
        if (obj == null) return null;
        if (obj instanceof Long) return (Long) obj;
        if (obj instanceof Integer) return ((Integer) obj).longValue();
        if (obj instanceof String) return Long.parseLong((String) obj);
        throw new IllegalArgumentException("Cannot convert to Long: " + obj.getClass());
    }

    protected List<Long> safeToLongList(Object obj) {
        if (obj == null) return Collections.emptyList();
        if (obj instanceof List) {
            return ((List<?>) obj).stream()
                    .map(this::safeToLong)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
        }
        return Collections.emptyList();
    }
}
